Repository navigation
Give pages without a slug their own canonical URL - #192
Merged
Merged
Conversation
Pages that aren't mapped to a slug were rewritten with the root slug, so they declared the home page as canonical URL and og:url and took over its per-page metadata, both in the worker and in the client script. Search engines could treat them as duplicates of the home page. Use the page ID path as their canonical URL (so /Title-<id> and /<id> share one), and apply no per-page metadata or generated OG image to them. Closes #190 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #190.
Pages that aren't mapped to a slug (opened at
/<page-id>or/<Title>-<page-id>) were rewritten with the root slug, both in the worker and in the client script. As a result, they:og:url, so search engines could treat them as duplicates of the home page;PAGE_METADATA['']): title, description, OG image and hreflang alternates.Changes:
slug = nullfor these pages, plus their canonical path:/<page-id>, so/Title-<id>and/<id>share one canonical URL. When the path has no page ID, the request path is used.appendJavascriptbuilds the canonical URL once and hands it toMetaRewriterandHeadRewriter.pageMetadata(slug)returns no per-page metadata fornull. It checks fornullexplicitly, so a slug literally named "null" can't leak its metadata./og-image/only renders pages with a slug, so they previously got the home page's image. The default OG image still applies.applyMetausesnullthe same way, so the home page's title no longer replaces the page's own title after load.Verification
npm test: 25 tests pass. Three tests are new. They run the worker's real head, meta and title handlers on fake elements, becauseHTMLRewriterisn't available in Node. Against the old code, only the test for pages without a slug fails; the other two guard against regressions.In
wrangler devagainst the live render check page, withPAGE_METADATA['']titled "Home title" and the unmapped database item Item Beta:/<id>or/Item-Beta-<id>og:urlset to the home pageog:urlset to/<id>document.title"Home title"document.title"Item Beta"Note
In the browser, the Notion client rewrites
link[rel=canonical]andog:urlto its own/Title-<id>path after it loads, on every page including the home page. This happened before this PR too. Since #191, crawlers that don't run JavaScript get the server-rendered page, where the worker's canonical URL is what counts. Keeping the canonical URL inapplyMetaas well would be a separate change.